﻿// Shader-Based-Image-Processing (SBIP)
// http://code.google.com/p/sbip/
//
// Copyright © Frank Nagl, 2009-2011
// admin@franknagl.de
//
namespace SBIP.Filter
{
    using System;

    /// <summary>
    /// Discrete convolution operator with a 3x3 filter <see cref="Kernel"/>.
    /// </summary>
    /// <remarks>
    /// <para>Convolution operators transforms an input image using a 
    /// mathematical function in an output image. Thereby, the mathematical 
    /// function in the discrete range is realized by a convolution mask, also 
    /// called filter <see cref="Kernel"/>. Typical convolution operations are 
    /// blurring, sharpening and edge detection.
    /// </para>
    /// 
    /// <para>Sample usage:</para>
    /// <code>
    /// Bitmap image = new Bitmap("cathedral.jpg");
    ///
    /// // 1. Offline rendering of images
    /// // create Processor, used as rendering framework
    /// Processor processor = new Processor( );
    /// // starts Processor
    /// processor.Begin( image );
    /// // create Laplace filter
    /// Convolution3x3 filter = new Convolution3x3( );
    /// processor.Filter = filter;
    /// // optional: configure filter
    /// filter.Kernel = new [] { 2, 2, 2, 2, 2, 2, 2, 2, 2 };
    /// filter.SetKernelCoefficient(4, 0);
    /// // apply the filter, render to bitmap  
    /// Bitmap resultImage = processor.RenderToBitmap( );
    /// resultImage.Save( "Convolution3x3.jpg", ImageFormat.Jpeg );
    /// // apply the filter, render to texture
    /// // Texture2D resultTexture = processor.RenderToTexture( );
    /// processor.End( );
    ///  
    /// // 2. Online rendering of videos or images
    /// // create any windows control for rendering in
    /// Form myForm = new Form
    /// {
    ///     Width = 1280,
    ///     Height = 720
    /// };
    /// // starts Processor
    /// processor.Begin( "Video.avi", myForm );
    /// // create Laplace filter
    /// filter = new Convolution3x3( );
    /// processor.Filter = filter;
    /// // optional: configure filter
    /// filter.Kernel = new [] { 2, 2, 2, 2, 2, 2, 2, 2, 2 };
    /// filter.SetKernelCoefficient(4, 0);
    /// // apply the filter
    /// myForm.Show( );
    /// while ( myForm.Created )
    /// {
    ///     processor.Render( );
    ///     Application.DoEvents( );
    /// }
    /// processor.End( );
    /// </code>
    /// 
    /// <para><b>Initial image:</b></para>
    /// <img src="../../Cathedral.jpg"/>
    /// <para><b>Result image:</b></para>
    /// <img src="../../Convolution3x3.jpg"/>
    /// </remarks>
    /// 
    /// <seealso cref="Convolution5x5"/>
    /// 
    public sealed class Convolution3x3 : BaseFilter
    {
        #region effect properties

        private int[] kernel;
        /// <summary>The convolution 3x3 mask as a 9-elements array 
        /// (filled row by row), also called filter kernel.</summary>
        public int[] Kernel
        {
            get { return kernel; }
            set
            {
                if (Effect == null)
                    throw new ArgumentException("Kernel" + InitMsg);

                kernel = value;
                Effect.Parameters["Kernel"].SetValue(value);
            }
        }
        #endregion effect properties

        /// <summary>
        /// Initializes a new instance of the <see cref="Convolution3x3"/> class.
        /// </summary>
        public Convolution3x3() : base("Convolution3x3") { }

        /// <summary>Defines Convolution3x3 default kernel.</summary>
        protected override void PostInit()
        {
            Kernel = new [] { 2, 2, 2, 2, 2, 2, 2, 2, 2 };
        }

        /// <summary>(Re-)Sets a specified kernel coefficient.</summary>
        /// <param name="index">The index of the coefficient in the 
        /// <see cref="Kernel"/>'s array (size 9).</param>
        /// <param name="value">The new value for the coefficient.</param>
        public void SetKernelCoefficient(int index, int value)
        {
            kernel[index] = value;
            Kernel = kernel;
        }
    }
}
